package router

import (
	_ "embed"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/gin-gonic/gin"
	"gtinlian.fun/src/auth"
	"gtinlian.fun/src/file_reader"
	"gtinlian.fun/src/htmls"
)

func SetupRoutes(r *gin.Engine, fileDir, authCode string, reader *file_reader.FileLineReader) {
	// 定义根路径 / 的路由，根据设备类型返回不同 HTML 内容
	r.GET("/", func(c *gin.Context) {
		// 获取 User-Agent 头信息
		userAgent := c.Request.UserAgent()
		// 判断是否为手机设备
		isMobile := strings.Contains(strings.ToLower(userAgent), "mobile")
		if isMobile {
			c.Data(http.StatusOK, "text/html; charset=utf-8", htmls.GetPhone())
		} else {
			c.Data(http.StatusOK, "text/html; charset=utf-8", htmls.GetIndex())
		}
	})

	// 定义 /files 路径的路由，返回 fileHTML 内容
	r.GET("/files", func(c *gin.Context) {
		c.Data(http.StatusOK, "text/html; charset=utf-8", htmls.GetFile())
	})

	// 定义 read 接口
	r.GET("/read", func(c *gin.Context) {
		line, err := reader.Read()
		if err != nil {
			c.JSON(500, gin.H{"error": err.Error()})
			return
		}
		c.JSON(200, gin.H{"line": line})
	})

	r.GET("/read/next", func(c *gin.Context) {
		reader.Next()
		line, err := reader.Read()
		if err != nil {
			c.JSON(500, gin.H{"error": err.Error()})
			return
		}
		c.JSON(200, gin.H{"line": line})
	})

	// 添加获取文件列表的接口
	r.GET("/list", func(c *gin.Context) {
		// 获取请求中的 path 参数，默认为空字符串，表示根目录
		pathParam := c.Query("path")
		// 拼接完整的目录路径
		targetDir := filepath.Join(fileDir, pathParam)

		// 检查目标目录是否存在
		if _, err := os.Stat(targetDir); os.IsNotExist(err) {
			c.JSON(http.StatusNotFound, gin.H{"error": "目录不存在"})
			return
		}

		files, err := os.ReadDir(targetDir)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}

		type FileInfo struct {
			Name    string `json:"name"`
			Size    int64  `json:"size"`
			ModTime string `json:"mod_time"`
			Mode    string `json:"mode"`
			IsDir   bool   `json:"is_dir"`
		}

		var fileInfos []FileInfo
		for _, file := range files {
			info, err := file.Info()
			if err != nil {
				continue
			}
			fileInfos = append(fileInfos, FileInfo{
				Name:    file.Name(),
				Size:    info.Size(),
				ModTime: info.ModTime().Format("2006-01-02 15:04:05"),
				Mode:    info.Mode().String(),
				IsDir:   file.IsDir(),
			})
		}

		// 无论是否有文件，都返回 files 字段为列表
		c.JSON(http.StatusOK, gin.H{"files": fileInfos})
	})

	// 添加获取文件详细信息的接口
	r.GET("/file-info/*filepath", func(c *gin.Context) {
		// 使用通配符获取完整路径
		fullPath := c.Param("filepath")
		// 去除路径前的斜杠，使用 strings.TrimPrefix 替代 if 语句
		fullPath = strings.TrimPrefix(fullPath, "/")

		// 检查路径是否包含非法字符
		if strings.ContainsAny(fullPath, `\*?"<>|`) {
			c.JSON(http.StatusBadRequest, gin.H{"error": "非法路径"})
			return
		}

		filePath := filepath.Join(fileDir, fullPath)

		// 检查文件是否存在
		info, err := os.Stat(filePath)
		if os.IsNotExist(err) {
			c.JSON(http.StatusNotFound, gin.H{"error": "文件不存在"})
			return
		}
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "获取文件信息失败"})
			return
		}

		// 检查路径是否合法，防止路径遍历攻击
		relPath, err := filepath.Rel(fileDir, filePath)
		if err != nil || strings.HasPrefix(relPath, "..") {
			c.JSON(http.StatusBadRequest, gin.H{"error": "非法文件访问"})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"name":     info.Name(),
			"size":     info.Size(),
			"mod_time": info.ModTime().Format("2006-01-02 15:04:05"),
			"mode":     info.Mode().String(),
			"is_dir":   info.IsDir(),
			"sys":      info.Sys(),
		})
	})

	// File download interface
	r.GET("/download/*filepath", func(c *gin.Context) {
		// 使用通配符获取完整路径
		fullPath := c.Param("filepath")
		// 去除路径前的斜杠，使用 strings.TrimPrefix 替代 if 语句
		fullPath = strings.TrimPrefix(fullPath, "/")

		// 检查路径是否包含非法字符
		if strings.ContainsAny(fullPath, `\*?"<>|`) {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Illegal file path"})
			return
		}

		filePath := filepath.Join(fileDir, fullPath)

		// Check if the file exists
		if _, err := os.Stat(filePath); os.IsNotExist(err) {
			c.JSON(http.StatusNotFound, gin.H{"error": "File does not exist"})
			return
		}

		// Check if the file is in the specified directory
		relPath, err := filepath.Rel(fileDir, filePath)
		if err != nil || strings.HasPrefix(relPath, "..") {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Illegal file access"})
			return
		}

		// 获取文件名
		filename := filepath.Base(filePath)
		// Handle file name encoding to solve Chinese garbled characters
		encodedFilename := url.QueryEscape(filename)
		c.Header("Content-Disposition", "attachment; filename*=UTF-8''"+encodedFilename)

		// Provide file download
		c.File(filePath)
	})

	// 文件上传接口
	r.POST("/upload", func(c *gin.Context) {
		authResult := auth.ValidateAuthCode(c, authCode)
		if !authResult.Success {
			c.JSON(authResult.StatusCode, gin.H{
				"success": authResult.Success,
				"message": authResult.Message,
			})
			return
		}

		// 获取前端传递的路径
		path := c.PostForm("path")
		if path == "" {
			path = "/"
		}

		// 获取上传的文件
		file, err := c.FormFile("file")
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"success": false,
				"message": "获取文件失败",
			})
			return
		}

		// 拼接完整的文件存储路径
		filePath := filepath.Join(fileDir, path, file.Filename)

		// 检查路径是否合法，防止路径遍历攻击
		relPath, err := filepath.Rel(fileDir, filePath)
		if err != nil || strings.HasPrefix(relPath, "..") {
			c.JSON(http.StatusBadRequest, gin.H{
				"success": false,
				"message": "非法的上传路径",
			})
			return
		}

		// 创建目录（如果不存在）
		dir := filepath.Dir(filePath)
		if err := os.MkdirAll(dir, 0755); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"success": false,
				"message": "创建目录失败",
			})
			return
		}

		// 保存文件到指定目录
		if err := c.SaveUploadedFile(file, filePath); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"success": false,
				"message": "保存文件失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"success": true,
			"message": "文件上传成功",
		})
	})

	// 定义认证接口
	r.POST("/authenticate", func(c *gin.Context) {
		authResult := auth.ValidateAuthCode(c, authCode)
		c.JSON(authResult.StatusCode, gin.H{
			"success": authResult.Success,
			"message": authResult.Message,
		})
	})

	// 创建文件夹接口
	r.POST("/create-folder", func(c *gin.Context) {
		authResult := auth.ValidateAuthCode(c, authCode)
		if !authResult.Success {
			c.JSON(authResult.StatusCode, gin.H{
				"success": authResult.Success,
				"message": authResult.Message,
			})
			return
		}

		// 获取请求中的文件夹名称和路径
		var request struct {
			Name string `json:"name"`
			Path string `json:"path"`
		}
		if err := c.ShouldBindJSON(&request); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"success": false,
				"message": "请求格式错误",
			})
			return
		}

		// 构建文件夹路径，在当前路径下创建
		folderPath := filepath.Join(fileDir, request.Path, request.Name)
		if err := os.MkdirAll(folderPath, 0755); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"success": false,
				"message": "创建文件夹失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"success": true,
			"message": "文件夹创建成功",
		})
	})

	// 删除文件接口
	r.POST("/delete-file", func(c *gin.Context) {
		authResult := auth.ValidateAuthCode(c, authCode)
		if !authResult.Success {
			c.JSON(authResult.StatusCode, gin.H{
				"success": authResult.Success,
				"message": authResult.Message,
			})
			return
		}

		// 获取请求中的文件路径
		var request struct {
			Path string `json:"path"`
		}
		if err := c.ShouldBindJSON(&request); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"success": false,
				"message": "请求格式错误",
			})
			return
		}

		// 构建完整文件路径
		filePath := filepath.Join(fileDir, request.Path)

		// 检查文件是否存在
		if _, err := os.Stat(filePath); os.IsNotExist(err) {
			c.JSON(http.StatusNotFound, gin.H{
				"success": false,
				"message": "文件不存在",
			})
			return
		}

		// 删除文件
		if err := os.Remove(filePath); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"success": false,
				"message": "删除文件失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"success": true,
			"message": "文件删除成功",
		})
	})

	// 删除目录接口（已有代码，可添加更多安全检查）
	r.POST("/delete-dir", func(c *gin.Context) {
		authResult := auth.ValidateAuthCode(c, authCode)
		if !authResult.Success {
			c.JSON(authResult.StatusCode, gin.H{
				"success": authResult.Success,
				"message": authResult.Message,
			})
			return
		}

		// 获取请求中的路径
		var request struct {
			Path string `json:"path"`
		}
		if err := c.ShouldBindJSON(&request); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"success": false,
				"message": "请求格式错误",
			})
			return
		}

		// 构建完整目录路径
		dirPath := filepath.Join(fileDir, request.Path)

		// 检查目录是否存在
		if _, err := os.Stat(dirPath); os.IsNotExist(err) {
			c.JSON(http.StatusNotFound, gin.H{
				"success": false,
				"message": "目录不存在",
			})
			return
		}

		// 不允许删除根目录
		if dirPath == fileDir {
			c.JSON(http.StatusForbidden, gin.H{
				"success": false,
				"message": "不能删除根目录",
			})
			return
		}

		// 删除目录
		if err := os.RemoveAll(dirPath); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"success": false,
				"message": "删除目录失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"success": true,
			"message": "目录删除成功",
		})
	})

	// 返回 icon.png 图片的接口
	r.GET("/icon.png", func(c *gin.Context) {
		c.Data(http.StatusOK, "image/png", htmls.GetIcon())
	})

	// 添加音频请求代理接口
	r.GET("/audit/*word", func(c *gin.Context) {
		// 获取路径中的单词
		word := c.Param("word")

		// 去除路径前的斜杠，使用 strings.TrimPrefix 替代 if 语句
		word = strings.TrimPrefix(word, "/")

		// 构造目标 URL
		targetURL := fmt.Sprintf("https://dict.youdao.com/dictvoice?audio=%s&type=2", url.QueryEscape(word))
		target, err := url.Parse(targetURL)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "目标 URL 解析失败"})
			return
		}

		// 创建反向代理
		proxy := httputil.NewSingleHostReverseProxy(target)

		// 修改请求的主机名和请求头
		proxy.Director = func(req *http.Request) {
			req.URL.Scheme = target.Scheme
			req.URL.Host = target.Host
			req.URL.Path = target.Path
			req.URL.RawQuery = target.RawQuery
			// 设置请求主机名
			req.Host = target.Host
			// 添加必要的请求头，模拟浏览器请求
			req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3")
			req.Header.Set("Accept", "*/*")
			req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
		}

		// 处理请求
		proxy.ServeHTTP(c.Writer, c.Request)
	})
}
